#include "netclient.h"
#include "../model/datacenter.h"

using namespace model;

namespace netWork {

static int getRecentMessagesCount = 100;

QString makeRequestId()
{
    return "R:" + QUuid::createUuid().toString();
}

void netWork::NetClient::ping()
{
    //创建请求
    QNetworkRequest httpReq;
    //设置请求地址
    httpReq.setUrl(HTTP_URL + "/ping");
    //调用get方法发送请求, 获取响应
    QNetworkReply* httpResp = httpClient.get(httpReq);
    //响应到来时, 进行处理逻辑
    connect(httpResp, &QNetworkReply::finished,this,[=](){
        //判断响应是否有误
        if(httpResp->error() != QNetworkReply::NoError)
        {
            LOG() << "void netWork::NetClient::ping() 获取响应失败!";
            httpResp->deleteLater();
            return;
        }
        //响应无误, 进行处理
        LOG() << "void netWork::NetClient::ping() 获取响应成功! resp = " << QString(httpResp->readAll()) ;
        httpResp->deleteLater();
    });
}

void NetClient::initWebsocket()
{
    connect(&webSocketClient,&QWebSocket::connected,this,[=](){
        LOG() << "webSocketClient 连接成功";
        //连接成功后需要发送身份验证信息
        sendAuth();
    });
    connect(&webSocketClient,&QWebSocket::disconnected,this,[=](){
        LOG() << "webSocketClient 连接断开";
    });
    connect(&webSocketClient,&QWebSocket::errorOccurred,this,[=](QAbstractSocket::SocketError error){
        LOG() << "webSocketClient 连接出错" << error;
    });
    connect(&webSocketClient,&QWebSocket::textMessageReceived,this,[=](const QString& message){
        LOG() << "webSocketClient 收到文本消息!" << message;
    });
    connect(&webSocketClient,&QWebSocket::binaryMessageReceived,this,[=](const QByteArray& byteArray){
        LOG() << "webSocketClient 收到二进制消息" << byteArray.length();
        bite_im::NotifyMessage notifyMessage;
        notifyMessage.deserialize(&pbSerializer,byteArray);
        //解析websocket消息
        handleWsResponse(notifyMessage);

    });

    //建立webSocket连接
    webSocketClient.open(WEBSOCKET_URL);
}

void NetClient::sendAuth()
{
    if (!webSocketClient.isValid())
    {
        LOG() << "webSocketClient 无效!";
        return;
    }

    bite_im::ClientAuthenticationReq req;

    req.setRequestId(makeRequestId());
    req.setSessionId(dataCenter->getLoginSessionId());
    QByteArray pbreq = req.serialize(&pbSerializer);
    webSocketClient.sendBinaryMessage(pbreq);

}
/////////////////////////////////////////////////////////////////////////////////
///网络通信数据方法
/////////////////////////////////////////////////////////////////////////////////
///
void NetClient::getMyself(const QString& loginSessionId)
{
    bite_im::GetUserInfoReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(dataCenter->getLoginSessionId());
    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[获取个人信息] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/get_user_info",body);
    //响应到来时, 进行处理
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        auto resp = handleHttpResponse<bite_im::GetUserInfoRsp>(httpResp);
        if(!resp)
        {
            LOG() << "NetClient::getMyself 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetUserInfoRsp>* resp 实例化结果为空!" ;
            return;
        }
        dataCenter->resetMyself(resp);

        emit dataCenter->getMyselfDone();

        LOG() << "[获取个人信息] 响应处理成功";

    });
}

void NetClient::getFriendList(const QString &loginSessionId)
{
    bite_im::GetFriendListReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(dataCenter->getLoginSessionId());
    QByteArray body = pbReq.serialize(&pbSerializer);
    LOG() << "[获取好友列表] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/get_friend_list",body);

    //响应到来时进行处理
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        auto resp = handleHttpResponse<bite_im::GetFriendListRsp>(httpResp);
        if(!resp)
        {
            LOG() << "NetClient::getFriendList 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetFriendListRsp>* resp 实例化结果为空!" ;
            return;
        }

        dataCenter->resetFriendList(resp);

        emit dataCenter->getFriendListDone();

        LOG() << "[获取好友列表] 响应处理成功";
    });
}

void NetClient::getChatSessionList(const QString &loginSessionId)
{
    //创建请求
    bite_im::GetChatSessionListReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[获取消息会话列表] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/get_chat_session_list", body);
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::GetChatSessionListRsp>(httpResp);

        //解析响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::getChatSessionList 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetChatSessionListRsp>* resp 实例化结果为空!" ;
            return;
        }

        //处理正确响应
        dataCenter->resetChatSessionList(resp);

        //发送信号
        emit dataCenter->getChatSessionListDone();

        LOG() << "[获取消息会话列表] 响应处理成功";
    });

}

void NetClient::getApplyList(const QString &loginSessionId)
{
    //创建请求
    bite_im::GetPendingFriendEventListReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[获取好友申请列表] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/get_pending_friend_events", body);
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        //解析响应
        auto resp = handleHttpResponse<bite_im::GetPendingFriendEventListRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::getApplyList 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetPendingFriendEventListRsp>* resp 实例化结果为空!" ;
            return;
        }

        //处理正确响应
        dataCenter->resetApplyList(resp);

        //发出信号
        emit dataCenter->getApplyListDone();

        LOG() << "[获取好友申请列表] 响应处理成功";
    });

}

void NetClient::getRecentMessages(const QString &loginSessionId, const QString &chatSessionId, bool updateUI)
{
    //创建请求
    bite_im::GetRecentMsgReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    //设置获取最近消息数量
    pbReq.setMsgCount(getRecentMessagesCount);
    //设置获取消息的会话id
    pbReq.setChatSessionId(chatSessionId);

    //序列化出二进制body数据
    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[获取最近消息] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    //发送请求, 获取响应
    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/message_transmit/new_message",body);
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::GetRecentMsgRsp>(httpResp);
        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::getRecentMessages 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetRecentMsgRsp>* resp 实例化结果为空!" ;
            return;
        }
        //解析响应
        dataCenter->resetRecentMessages(chatSessionId,resp);

        //发出信号
        if(updateUI)
        {
            emit dataCenter->getRecentMessageListDone(chatSessionId);
        }
        else
        {
            emit dataCenter->getRecentMessageListDoneNoUI(chatSessionId);
        }

        LOG() << "[获取最近消息] 响应处理成功";
    });
}

void NetClient::sendMessage(const QString &loginSessionId, const QString &chatSessionId, const QByteArray &content, model::MessageType type, const QString &extraInfo)
{
    //创建请求
    bite_im::NewMessageReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionId(chatSessionId);

    bite_im::MessageContent message;
    switch(type)
    {
        //文本消息
    case model::MessageType::TEXT_TYPE:
        {
            message.setMessageType(bite_im::MessageTypeGadget::MessageType::STRING);

            bite_im::StringMessageInfo stringMessageInfo;
            stringMessageInfo.setContent(QString(content));

            message.setStringMessage(stringMessageInfo);
        }
    break;
        //文件消息
    case model::MessageType::FILE_TYPE:
    {
        message.setMessageType(bite_im::MessageTypeGadget::MessageType::FILE);

        bite_im::FileMessageInfo fileMessageInfo;
        fileMessageInfo.setFileSize(content.size());
        fileMessageInfo.setFileName(extraInfo);
        fileMessageInfo.setFileContents(content);

        message.setFileMessage(fileMessageInfo);
    }
    break;
    case model::MessageType::IMAGE_TYPE:
    {
        message.setMessageType(bite_im::MessageTypeGadget::MessageType::IMAGE);

        bite_im::ImageMessageInfo imageMessageInfo;
        imageMessageInfo.setFileId("");
        imageMessageInfo.setImageContent(content);

        message.setImageMessage(imageMessageInfo);
    }
    break;
    case model::MessageType::SPEECH_TYPE:
    {
        message.setMessageType(bite_im::MessageTypeGadget::MessageType::SPEECH);

        bite_im::SpeechMessageInfo speechMessageInfo;
        speechMessageInfo.setFileId("");
        speechMessageInfo.setFileContents(content);

        message.setSpeechMessage(speechMessageInfo);
    }
    break;
    default:
        LOG() << "NetClient::sendMessage 未知类型!";
    break;
    }

    pbReq.setMessage(message);

    LOG() << "[发送消息] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    //请求序列化
    QByteArray body = pbReq.serialize(&pbSerializer);

    //发送请求, 获取响应
    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/message_transmit/new_message",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::NewMessageRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::getRecentMessages 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetRecentMsgRsp>* resp 实例化结果为空!" ;
            return;
        }

        //解析响应, 这里不需要该操作

        //发送信号
        emit dataCenter->sendMessageDone(content,type,extraInfo);

        LOG() << "[发送消息] 响应处理成功";

    });

}

void NetClient::receiveMessage(const QString &chatSessionId)
{
    //该函数负责收取消息后的页面处理, 需要判断传入的会话是否为选中会话, 是选中会话则更新最后一条消息, 并更新消息展示区, 不是选中会话则更新最后一条消息,并更新未读消息数目
    if(chatSessionId == dataCenter->getCurrentChatSessionId())
    {
        //更新消息展示区
        const Message& lastMessage = dataCenter->getRecentMessages(chatSessionId)->back();
        emit dataCenter->receiveMessageDone(lastMessage);
    }
    else
    {
        //更新特定会话的未读消息数目
        dataCenter->addUnread(chatSessionId);
    }

    //发送统一更新最后一条消息展示的信号
    emit dataCenter->updateLastMessage(chatSessionId);
}

void NetClient::changeNickname(const QString &loginSessionId, const QString &nickname)
{
    //创建请求

    bite_im::SetUserNicknameReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setUserId("");
    pbReq.setNickname(nickname);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[改变个人信息昵称] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/set_nickname", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::SetUserNicknameRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::changeNickname 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::SetUserNicknameRsp>* resp 实例化结果为空!" ;
            return;
        }

        //把数据设置到dataCenter中
        dataCenter->resetNickname(nickname);

        //发送信号
        emit dataCenter->changeNicknameDone();

        LOG() << "[改变个人信息昵称] 响应处理成功";
    });

}

void NetClient::changeDescription(const QString &loginSessionId, const QString &description)
{
    //创建请求
    bite_im::SetUserDescriptionReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setDescription(description);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[改变个人信息签名] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/set_description", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::SetUserDescriptionRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::changeDescription 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::SetUserDescriptionRsp>* resp 实例化结果为空!" ;
            return;
        }

        //把数据设置到dataCenter中
        dataCenter->resetDescription(description);

        //发送信号
        emit dataCenter->changeDescriptionDone();

        LOG() << "[改变个人信息签名] 响应处理成功";
    });

}

void NetClient::getVerifyCode(const QString &phone)
{
    //创建请求
    bite_im::PhoneVerifyCodeReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setPhoneNumber(phone);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[获取验证码] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/get_phone_verify_code", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::PhoneVerifyCodeRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::getVerifyCode 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::PhoneVerifyCodeRsp>* resp 实例化结果为空!" ;
            return;
        }

        //把数据设置到dataCenter中
        dataCenter->resetVerifyCodeId(resp);

        //发送信号
        emit dataCenter->getVerifyCodeDone();

        LOG() << "[获取验证码] 响应处理成功";
    });

}

void NetClient::changePhone(const QString loginSessionId, const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    //创建请求
    bite_im::SetUserPhoneNumberReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setPhoneNumber(phone);
    pbReq.setPhoneVerifyCodeId(verifyCodeId);
    pbReq.setPhoneVerifyCode(verifyCode);

    //序列化出二进制数据
    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[改变个人信息电话] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    //获取响应
    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/set_phone",body);

    connect(httpResp,&QNetworkReply::finished,this, [=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::SetUserPhoneNumberRsp>(httpResp);

        //解析响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::changePhone 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::SetUserPhoneNumberRsp>* resp 实例化结果为空!" ;
            return;
        }

        //把数据设置到dataCenter中
        dataCenter->resetPhone(phone);

        //发送信号
        emit dataCenter->changePhoneDone();

        LOG() << "[改变个人信息电话] 响应处理成功";

    });
}

void NetClient::changeAvatar(const QString loginSessionId, const QByteArray &avatar)
{
    //构建请求
    bite_im::SetUserAvatarReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setAvatar(avatar);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[改变个人信息头像] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/set_avatar", body);

    connect(httpResp,&QNetworkReply::finished,this, [=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::SetUserAvatarRsp>(httpResp);

        //解析响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::changeAvatar 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::SetUserAvatarRsp>* resp 实例化结果为空!" ;
            return;
        }

        //把数据设置到dataCenter中
        dataCenter->resetAvatar(avatar);

        //发送信号
        emit dataCenter->changeAvatarDone();

        LOG() << "[改变个人信息头像] 响应处理成功";

    });
}

void NetClient::deleteFriend(const QString &loginSessionId, const QString &userId)
{
    //创建请求
    bite_im::FriendRemoveReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setPeerId(userId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[删除好友] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/remove_friend", body);

    connect(httpResp,&QNetworkReply::finished,this, [=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::FriendRemoveRsp>(httpResp);

        //解析响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::deteleFriend 函数处理 响应信号出现问题, 原因: std::shared_ptr<NetClient::deteleFriendRsp>* resp 实例化结果为空!" ;
            return;
        }

        //把数据设置到dataCenter中
        dataCenter->removeFriend(userId);

        //发送信号
        emit dataCenter->deleteFriendDone();

        LOG() << "[删除好友] 响应处理成功";

    });

}

void NetClient::addFriendApply(const QString &loginSessionId, const QString &userId)
{
    //创建请求
    bite_im::FriendAddReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    pbReq.setRespondentId(userId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[发送好友申请] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/add_friend_apply", body);

    connect(httpResp,&QNetworkReply::finished,this, [=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::FriendAddRsp>(httpResp);

        //解析响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::addFriendApply 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::FriendAddRsp>* resp 实例化结果为空!" ;
            return;
        }

        //不需要把数据设置到dataCenter中

        //发送信号
        emit dataCenter->addFriendApplyDone();

        LOG() << "[发送好友申请] 响应处理成功";
    });
}

void NetClient::acceptFriendApply(const QString &loginSessionId, const QString &userId)
{
    //
    bite_im::FriendAddProcessReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setNotifyEventId("");
    pbReq.setAgree(true);
    pbReq.setApplyUserId(userId);
    pbReq.setSessionId(loginSessionId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[同意好友申请] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/add_friend_process", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::FriendAddProcessRsp>(httpResp);

        //检查响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::acceptFriendApply 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::FriendAddProcessRsp>* resp 实例化结果为空!" ;
            return;
        }

        //处理响应
        //删除元素
        UserInfo user = dataCenter->removeFromApplyList(userId);
        //新增元素
        dataCenter->getFriendList()->push_front(user);


        //发送信号
        emit dataCenter->acceptFriendApplyDone(userId);

        LOG() << "[同意好友申请] 响应处理成功";
    });
}

void NetClient::rejectFriendApply(const QString &loginSessionId, const QString &userId)
{
    bite_im::FriendAddProcessReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setNotifyEventId("");
    pbReq.setAgree(false);
    pbReq.setApplyUserId(userId);
    pbReq.setSessionId(loginSessionId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[拒绝好友申请] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/add_friend_process", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::FriendAddProcessRsp>(httpResp);

        //检查响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::rejectFriendApply 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::FriendAddProcessRsp>* resp 实例化结果为空!" ;
            return;
        }

        //处理响应
        //删除元素
        UserInfo user = dataCenter->removeFromApplyList(userId);

        //发送信号
        emit dataCenter->rejectFriendApplyDone(userId);

        LOG() << "[拒绝好友申请] 响应处理成功";
    });
}

void NetClient::createGroupChatSession(const QString &loginSessionId, const QList<QString> &list)
{
    //创建请求
    bite_im::ChatSessionCreateReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionName("新的群聊");
    pbReq.setMemberIdList(list);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[创建群聊会话] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    //发送请求, 获取响应
    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/create_chat_session", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::ChatSessionCreateRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::createGroupChatSession 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::ChatSessionCreateRsp>* resp 实例化结果为空!" ;
            return;
        }

        //将结果保存到本地(但这里不需要该逻辑, 因为当会话真正创建好后, 会由websocket进行推送)

        //发送信号
        emit dataCenter->createGroupChatSessionDone();

        LOG() << "[创建群聊会话] 响应处理成功";
    });

}

void NetClient::getMemberList(const QString &loginSessionId, const QString &chatSessionId)
{
    //创建请求
    bite_im::GetChatSessionMemberReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionId(chatSessionId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[群聊会话成员列表获取] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/get_chat_session_member", body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::GetChatSessionMemberRsp>(httpResp);

        //检测响应是否正确
        if(!resp)
        {
            LOG() << "NetClient::createGroupChatSession 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetChatSessionMemberRsp>* resp 实例化结果为空!" ;
            return;
        }

        //将结果保存到本地

        dataCenter->resetMemberList(chatSessionId,resp->memberInfoList());

        //发送信号
        emit dataCenter->getMemberListDone(chatSessionId);

        LOG() << "[群聊会话成员列表获取] 响应处理成功";
    });

}

void NetClient::searchUser(const QString &loginSessionId, const QString &searchKey)
{
    //创建请求
    bite_im::FriendSearchReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSearchKey(searchKey);
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[搜索用户] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/friend/search_friend",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::FriendSearchRsp>(httpResp);

        //检测响应结果是否正确
        if(!resp)
        {
            LOG() << "NetClient::searchUser 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::FriendSearchRsp>* resp 实例化结果为空!" ;
            return;
        }

        //解析响应, 保存数据到本地
        dataCenter->resetSearchUserResult(resp->userInfo());

        //发送信号
        emit dataCenter->searchUserDone();

        //打印日志
        LOG() << "[搜索用户] 响应处理成功";
    });

}

void NetClient::searchMessageBySearchKey(const QString &loginSessionId, const QString &chatSessionId, const QString &searchKey)
{
    //创建请求
    bite_im::MsgSearchReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(chatSessionId);
    pbReq.setChatSessionId(chatSessionId);
    pbReq.setSearchKey(searchKey);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[根据关键词搜索历史消息] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/message_storage/search_history",body);

    connect(httpResp, &QNetworkReply::finished, this, [=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::MsgSearchRsp>(httpResp);

        if(!resp)
        {
            LOG() << "NetClient::searchMessageBySearchKey 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::MsgSearchRsp>* resp 实例化结果为空!" ;
            return;
        }

        //保存数据
        dataCenter->resetSearchMessageResult(resp->msgList());

        //发送信号
        emit dataCenter->searchMessageDone();

        //打印日志
        LOG() << "[根据关键词搜索历史消息] 响应处理成功";

    });

}

void NetClient::searchMessageByTime(const QString &loginSessionId, const QString &chatSessionId, const QDateTime &beginTime, const QDateTime &endTime)
{
    //创建请求
    bite_im::GetHistoryMsgReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setChatSessionId(chatSessionId);
    pbReq.setStartTime(beginTime.toSecsSinceEpoch());
    pbReq.setOverTime(endTime.toSecsSinceEpoch());
    pbReq.setSessionId(chatSessionId);
    pbReq.setSessionId(loginSessionId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[根据时间获取历史消息] 发送请求 requestId=" << pbReq.requestId() << ", loginSessionId=" << loginSessionId;

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/message_storage/get_history",body);

    connect(httpResp, &QNetworkReply::finished, this, [=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::GetHistoryMsgRsp>(httpResp);

        if(!resp)
        {
            LOG() << "NetClient::searchMessageByTime 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetHistoryMsgRsp>* resp 实例化结果为空!" ;
            return;
        }

        //保存数据
        dataCenter->resetSearchMessageResult(resp->msgList());

        //发送信号
        emit dataCenter->searchMessageDone();

        //打印日志
        LOG() << "[根据时间获取历史消息] 响应处理成功";
    });
}

void NetClient::userLogin(const QString &username, const QString &password)
{
    //创建请求
    bite_im::UserLoginReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setNickname(username);
    pbReq.setPassword(password);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[根据用户密码进行登录] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/username_login",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::UserLoginRsp>(httpResp);

        if(!resp)
        {
            LOG() << "NetClient::userLogin 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::UserLoginRsp>* resp 实例化结果为空!" ;

            //发送信号
            emit dataCenter->userLoginDone(false, "网络故障");
            return;
        }

        if(!resp->success())
        {
            //发送信号
            emit dataCenter->userLoginDone(false, resp->errmsg());
        }

        //保存loginSessionId到本地

        dataCenter->resetLoginSessionId(resp->loginSessionId());

        //发送信号
        emit dataCenter->userLoginDone(true,"");

        //打印日志
        LOG() << "[根据用户密码进行登录] 响应处理成功";
    });

}

void NetClient::userRegister(const QString &username, const QString &password)
{
    //创建请求
    bite_im::UserRegisterReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setNickname(username);
    pbReq.setPassword(password);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[根据用户密码进行注册] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/username_register",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){
        //处理响应
        auto resp = handleHttpResponse<bite_im::UserRegisterRsp>(httpResp);

        if(!resp)
        {
            LOG() << "NetClient::userRegister 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::UserRegisterRsp>* resp 实例化结果为空!" ;
            emit dataCenter->userRegisterDone(false,"网络故障");
            return;
        }

        if(!resp->success())
        {
            emit dataCenter->userRegisterDone(false,resp->errmsg());
        }

        //无需任何本地化操作

        //发送信号
        emit dataCenter->userRegisterDone(true,"");

        //打印日志
        LOG() << "[根据用户密码进行注册] 响应处理成功";
    });
}

void NetClient::phoneLogin(const QString &phone, const QString &verifyCode)//
{
    bite_im::PhoneLoginReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setPhoneNumber(phone);
    pbReq.setVerifyCodeId(dataCenter->getVerifyCodeId());
    pbReq.setVerifyCode(verifyCode);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[根据电话进行登录] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/phone_login",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){

        //处理响应
        auto resp = handleHttpResponse<bite_im::PhoneLoginRsp>(httpResp);

        if(!resp)
        {
            LOG() << "NetClient::phoneLogin 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::PhoneLoginRsp>* resp 实例化结果为空!" ;
            emit dataCenter->phoneLoginDone(false,"网络故障");
            return;
        }

        if(!resp->success())
        {
            emit dataCenter->phoneLoginDone(false,resp->errmsg());
        }

        //保存loginSessionId到本地

        dataCenter->resetLoginSessionId(resp->loginSessionId());

        //发送信号
        emit dataCenter->phoneLoginDone(true,"");

        //打印日志
        LOG() << "[根据电话进行登录] 响应处理成功";
    });

}

void NetClient::phoneRegister(const QString &phone, const QString &verifyCode)//
{
    bite_im::PhoneRegisterReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setPhoneNumber(phone);
    pbReq.setVerifyCodeId(dataCenter->getVerifyCodeId());
    pbReq.setVerifyCode(verifyCode);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[根据电话进行注册] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/user/phone_register",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){

        //处理响应
        auto resp = handleHttpResponse<bite_im::PhoneRegisterRsp>(httpResp);

        if(!resp)
        {
            LOG() << " NetClient::phoneRegister 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::PhoneRegisterRsp>* resp 实例化结果为空!" ;
            emit dataCenter->phoneRegisterDone(false,"网络故障");
            return;
        }

        if(!resp->success())
        {
            emit dataCenter->phoneRegisterDone(false,resp->errmsg());
        }

        //无需任何本地化操作

        //发送信号
        emit dataCenter->phoneRegisterDone(true,"");

        //打印日志
        LOG() << "[根据电话进行注册] 响应处理成功";
    });
}

void NetClient::getSingleFile(const QString &loginSessionId, const QString &fileId)
{
    bite_im::GetSingleFileReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setFileId(fileId);
    pbReq.setSessionId(loginSessionId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[获取文件内容] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/file/get_single_file",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){

        //处理响应
        auto resp = handleHttpResponse<bite_im::GetSingleFileRsp>(httpResp);

        if(!resp)
        {
            LOG() << " NetClient::getSingleFile 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::GetSingleFileRsp>* resp 实例化结果为空!" ;
            return;
        }

        //无需任何本地化操作

        //发送信号
        emit dataCenter->getSingleFileDone(fileId,resp->fileData().fileContent());

        //打印日志
        LOG() << "[获取文件内容] 响应处理成功";
    });
}

void NetClient::speechConvertText(const QString &loginSessionId, const QString &fileId, const QByteArray& content) //
{
    //创建请求
    bite_im::SpeechRecognitionReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSpeechContent(content);
    pbReq.setSessionId(loginSessionId);

    QByteArray body = pbReq.serialize(&pbSerializer);

    LOG() << "[语音转文字] 发送请求 requestId=" << pbReq.requestId();

    QNetworkReply* httpResp = sendHttpRequest(HTTP_URL + "/service/speech/recognition",body);

    connect(httpResp,&QNetworkReply::finished,this,[=](){

        //处理响应
        auto resp = handleHttpResponse<bite_im::SpeechRecognitionRsp>(httpResp);

        if(!resp)
        {
            LOG() << " NetClient::speechConvertText 函数处理 响应信号出现问题, 原因: std::shared_ptr<bite_im::SpeechRecognitionRsp>* resp 实例化结果为空!" ;
            return;
        }

        //无需任何本地化操作

        //发送信号
        emit dataCenter->speechConvertTextDone(fileId,resp->recognitionResult());

        //打印日志
        LOG() << "[语音转文字] 响应处理成功";
    });
}
/////////////////////////////////////////////////////////////////////////////////////
/// 请求/响应逻辑
///
QNetworkReply* NetClient::sendHttpRequest(const QString &apiPath, const QByteArray &body)
{
    //构建HTTP完整请求
    QNetworkRequest httpReq;

    //设置HTTP报头值
    httpReq.setUrl(apiPath);

    //非Qt 6.8 形式
    //httpReq.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-protobuf");

    //Qt 6.8形式
    QHttpHeaders httpHeader;
    httpHeader.append("Content-Type","application/x-protobuf");
    httpReq.setHeaders(httpHeader);

    //调用post方法, 将完整请求发送
    QNetworkReply* httpResp = httpClient.post(httpReq,body);
    return httpResp;
}

///HTTP响应逻辑因泛型编程,直接定义在类中
void NetClient::handleWsResponse(const bite_im::NotifyMessage &notifyMessage)
{
    //解析NotifyMessage
    switch(notifyMessage.notifyType())
    {
    /// 接收消息
    case bite_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY:
    {
        Message msg;
        msg.load(notifyMessage.newMessageInfo().messageInfo());
        handleWsMessage(msg);
    }
    break;

    /// 删除好友
    case bite_im::NotifyTypeGadget::NotifyType::FRIEND_REMOVE_NOTIFY:
    {
        handleWsRemoveFriend(notifyMessage.friendRemove().userId());
    }
    break;

    /// 好友添加
    case bite_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_APPLY_NOTIFY:
    {
        UserInfo userInfo;
        userInfo.load(notifyMessage.friendAddApply().userInfo());
        handleWsAddFriendApply(userInfo);
    }
    break;

    /// 好友申请结果
    case bite_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY:
    {
        UserInfo userInfo;
        userInfo.load(notifyMessage.friendProcessResult().userInfo());
        handleWsAddFriendProcess(userInfo,notifyMessage.friendProcessResult().agree());
    }
    break;

    /// 群聊会话推送
    case bite_im::NotifyTypeGadget::NotifyType::CHAT_SESSION_CREATE_NOTIFY:
    {
        model::ChatSessionInfo chatSessionInfo;
        chatSessionInfo.load(notifyMessage.newChatSessionInfo().chatSessionInfo());
        handleWsSessionCreate(chatSessionInfo);
    }
    break;


    }
}

void NetClient::handleWsMessage(const model::Message &message)
{
    //获取消息列表指针
    QList<Message>* messageList = dataCenter->getRecentMessages(message.SessionId);

    //判断列表指针是否为空, 为空则从网络加载,不为空则从本地加载
    if(messageList == nullptr)
    {
        connect(dataCenter,&DataCenter::getRecentMessageListDoneNoUI,this,&NetClient::receiveMessage,Qt::UniqueConnection);
        dataCenter->getRecentMessagesAsync(message.SessionId,false);
    }
    else
    {
        //本地加载, 直接向dataCenter中添加数据
        dataCenter->getRecentMessages(message.SessionId)->push_back(message);
        //调用receiveMessage,进行页面逻辑处理
        receiveMessage(message.SessionId);
    }
}

void NetClient::handleWsRemoveFriend(const QString &userId)
{
    dataCenter->removeFriend(userId);
    dataCenter->deleteFriendDone();
}
/// 添加好友
void NetClient::handleWsAddFriendApply(const model::UserInfo &userInfo)
{
    // 1. DataCenter 中有一个 好友申请列表. 需要把这个数据添加到好友申请列表中
    QList<UserInfo>* applyList = dataCenter->getApplyList();
    if (applyList == nullptr) {
        LOG() << " NetClient::handleWsAddFriendApply 客户端没有加载到好友申请列表!";
        return;
    }
    // 把新的元素放到列表前面
    applyList->push_front(userInfo);

    // 2. 通知界面更新.
    emit dataCenter->receiveFriendApplyDone();
}

void NetClient::handleWsAddFriendProcess(const model::UserInfo &userInfo, bool agree)
{
    //同意逻辑
    if(agree)
    {
        QList<UserInfo>* friendList = dataCenter->getFriendList();
        if(friendList == nullptr)
        {
            LOG() << "NetClient::handleWsAddFriendProcess失败, 好友列表不存在";
            return;
        }

        friendList->push_front(userInfo);
        emit dataCenter->receiveFriendProcessAccept(userInfo);

    }
    //拒绝逻辑
    else
    {
        emit dataCenter->receiveFriendProcessReject(userInfo);
    }
}

void NetClient::handleWsSessionCreate(const model::ChatSessionInfo &chatSessionInfo)
{
    QList<ChatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();

    chatSessionList->push_front(chatSessionInfo);

    //发送信号,通知页面更新
    emit dataCenter->receiveSessionCreateDone();

}

}












